#include "mpdserver.h"

#include <QtNetwork/QTcpServer>
#include <QtNetwork/QTcpSocket>
#include <QTextStream>

MpdServer::MpdServer(QHostAddress address, quint16 port, QObject *parent) :
    QObject(parent)
{
    _srv = new QTcpServer(this);
    _srv->listen(address, port);

    connect(_srv, SIGNAL(newConnection()), SLOT(acceptConnection()));
}

MpdServer::~MpdServer()
{
    delete _srv;
}

void MpdServer::acceptConnection()
{
    while ( _srv->hasPendingConnections() )
    {
        QTcpSocket* sock = _srv->nextPendingConnection();
        connect(sock, SIGNAL(disconnected()), sock, SLOT(clientDisconnected()));
        //connect(sock, SIGNAL(error(QAbstractSocket::SocketError)), SLOT(socketError(QAbstractSocket::SocketError)));
        connect(sock, SIGNAL(readyRead()), SLOT(parseIncoming()));
        _clients.append(sock);
        sock->write("OK");
    }
}

void MpdServer::clientDisconnected()
{
    foreach(QTcpSocket* sock, _clients)
    {
        if ( sock->state() == QAbstractSocket::ClosingState ||
                sock->state() == QAbstractSocket::UnconnectedState )
        {
            _clients.removeOne(sock);
            delete sock;
            sock = NULL;
        }
    }
}

void MpdServer::parseIncoming()
{
    foreach(QTcpSocket* sock, _clients)
    {
        if (sock && sock->bytesAvailable() > 0)
            parseIncoming(sock);
    }
}

void MpdServer::parseIncoming(QTcpSocket* sock)
{
    if (!sock || sock->state() != QAbstractSocket::ConnectedState)
        return;

    qint64 len = sock->bytesAvailable();
    QByteArray msg = sock->read(len);
    if ( msg.length() < 1 )
        return;

    QString str_msg(msg);
    if (str_msg.startsWith("status"))
    {
        StatusInfo status;
        emit statusRequested(&status);
        reportStatus(sock, &status);
    }
    else if (str_msg.startsWith("currentsong"))
    {
        SongInfo song;
        emit currentSongRequested(&song);
        reportCurrentSong(sock, &song);
    }
}

void MpdServer::reportCurrentSong(QTcpSocket* sock, const SongInfo* args)
{
    if ( !sock )
        return;

    QByteArray out;
    QTextStream(&out)  << "artist: " << (args ? args->artist   : "") << '\n'
                       << "title: "  << (args ? args->title    : "") << '\n'
                       << "album: "  << (args ? args->album    : "") << '\n';
    sock->write(out);
    sock->flush();
}

void MpdServer::reportStatus(QTcpSocket* sock, const StatusInfo* status)
{
    if ( !sock )
        return;
    if ( !status )
    {
        sock->write("state: stop\n");
        return;
    }

    QByteArray out;
    QTextStream(&out)   << "volume: "           << status->volume               << '\n'
                        << "repeat: "           << (status->repeat   ? 1 : 0)   << '\n'
                        << "single: "           << (status->single   ? 1 : 0)   << '\n'
                        << "consume: "          << (status->consume  ? 1 : 0)   << '\n'
                        << "playlist: "         << status->playlistversion      << '\n'
                        << "playlistlength: "   << status->playlistlength       << '\n'
                        << "state: "            << status->state                << '\n'
                        << "song: "             << status->song                 << '\n'
                        << "songid: "           << status->songid               << '\n'
                        << "nextsong: "         << status->nextsong             << '\n'
                        << "nextsongid: "       << status->nextsongid           << '\n'
                        << "time: "             << status->time                 << '\n'
                        << "elapsed: "          << status->elapsed              << '\n'
                        << "bitrate: "          << status->bitrate              << '\n'
                        << "xfade: "            << status->xfade                << '\n'
                        << "audio: "            << status->audio                << '\n'
                        << "error: "            << status->error                << '\n';

    sock->write(out);
    //sock->flush();
}
